package com.friend.uu;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.bluetooth.BluetoothHeadset;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

import androidx.annotation.NonNull;

public class MusicFragment extends Fragment implements View.OnClickListener {

    private static final List<String> playlist = new ArrayList<>();
    private static final MediaPlayer mPlayer = new MediaPlayer();
    private static final String[] musicPermissions;
    private static final int MUSIC_PMS_CODE = 799979;
    private final Handler mHandler = new Handler();
    private final MusicPlayCtrl musicCtrl = new MusicPlayCtrl();
    private boolean isRandom = false;
    private MediaEventReceiver mMediaEventReceiver;
    private Activity mActivity;

    private SeekBar sbDuration;
    private TextView tvTitle, tvTime;

    static {
        musicPermissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE};
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mActivity = getActivity();
        validatePermission();
        mMediaEventReceiver = new MediaEventReceiver(new MediaEventReceiver
                .ReceivedListener() {
            @Override
            public void onReceived(MediaEventReceiver.MusicCtrl ctrl) {
                switch (ctrl) {
                    case playOrPause:
                        musicCtrl.playOrPause();
                        break;
                    case pause:
                        musicCtrl.pause();
                        break;
                    case next:
                        musicCtrl.playNext();
                        break;
                    case previous:
                        musicCtrl.playPrev();
                        break;
                }
            }
        });
        registerMediaReceiver();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_music, container, false);
        bindView(view);
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                if (!mPlayer.isPlaying()) return;
                final int t = mPlayer.getCurrentPosition() / 1000;
                final int d = mPlayer.getDuration() / 1000;
                final String str = String.format(
                        Locale.getDefault(),
                        "%02d:%02d:%02d/%02d:%02d:%02d",
                        t / 3600, (t % 3600) / 60, t % 60,
                        d / 3600, (d % 3600) / 60, d % 60);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        tvTime.setText(str);
                        sbDuration.setMax(d);
                        sbDuration.setProgress(t);
                    }
                });
            }
        }, 0, 1000);
        mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                musicCtrl.playNext();
            }
        });
        return view;
    }

    @Override
    public void onDestroy() {
        unregisterMediaReceiver();
        if (mPlayer.isPlaying()) mPlayer.stop();
        super.onDestroy();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode != MUSIC_PMS_CODE) return;
        if (isExternalReadable()) {
            upPlaylist();
        }
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.music_music_play) {
            musicCtrl.start();
        } else if (id == R.id.music_btn_pause) {
            musicCtrl.pause();
        } else if (id == R.id.music_btn_stop) {
            musicCtrl.stop();
        } else if (id == R.id.music_btn_prev) {
            musicCtrl.playPrev();
        } else if (id == R.id.music_btn_next) {
            musicCtrl.playNext();
        } else if (id == R.id.music_btn_random) {
            if (isRandom) {
                Collections.sort(playlist);
            } else {
                Collections.shuffle(playlist);
            }
            isRandom = !isRandom;
            int ic = isRandom ? R.drawable.ic_shuffle : R.drawable.ic_sort;
            v.setBackgroundResource(ic);
        } else if (id == R.id.music_btn_list) {
            showPlayList();
        }
    }

    private void bindView(View rootView) {
        rootView.findViewById(R.id.music_music_play).setOnClickListener(this);
        rootView.findViewById(R.id.music_btn_pause).setOnClickListener(this);
        rootView.findViewById(R.id.music_btn_stop).setOnClickListener(this);
        rootView.findViewById(R.id.music_btn_prev).setOnClickListener(this);
        rootView.findViewById(R.id.music_btn_next).setOnClickListener(this);
        rootView.findViewById(R.id.music_btn_random).setOnClickListener(this);
        rootView.findViewById(R.id.music_btn_list).setOnClickListener(this);

        sbDuration = rootView.findViewById(R.id.music_sb_progress);
        tvTitle = rootView.findViewById(R.id.music_tv_title);
        tvTime = rootView.findViewById(R.id.music_tv_time);
        sbDuration.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                if (mPlayer.isPlaying()) {
                    mPlayer.seekTo(seekBar.getProgress() * 1000);
                }
            }
        });
    }

    private boolean isExternalReadable() {
        return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
                mActivity.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
                        == PackageManager.PERMISSION_GRANTED;
    }

    private void validatePermission() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            upPlaylist();
            return;
        }
        for (String permission : musicPermissions) {
            if (mActivity.checkSelfPermission(permission) !=
                    PackageManager.PERMISSION_GRANTED) {
                requestPermissions(musicPermissions, MUSIC_PMS_CODE);
                return;
            }
        }
        upPlaylist();
    }

    // 取消监听
    private void unregisterMediaReceiver() {
        mActivity.unregisterReceiver(mMediaEventReceiver);
        AudioManager am = (AudioManager) mActivity.getSystemService(Context.AUDIO_SERVICE);
        ComponentName cName = new ComponentName(mActivity.getPackageName(),
                MediaEventReceiver.class.getName());
        am.unregisterMediaButtonEventReceiver(cName);
    }

    // 注册耳机事件监听
    private void registerMediaReceiver() {
        // Connect state
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_HEADSET_PLUG);
        filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        mActivity.registerReceiver(mMediaEventReceiver, filter);
        // Media Button event
        AudioManager aManager = (AudioManager) mActivity.getSystemService(Context.AUDIO_SERVICE);
        ComponentName cName = new ComponentName(mActivity.getPackageName(),
                MediaEventReceiver.class.getName());
        aManager.registerMediaButtonEventReceiver(cName);
    }


    void showMsg(String msg) {
        Toast.makeText(mActivity, msg, Toast.LENGTH_LONG).show();
    }

    void upPlaylist() {
        Cursor cur = mActivity.getContentResolver().query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                null, null, null, null);
        int i = cur.getColumnIndex(MediaStore.Audio.Media.DATA);
        while (cur.moveToNext()) {
            playlist.add(cur.getString(i));
        }
        cur.close();
    }

    class MusicPlayCtrl {

        boolean isPaused = false;
        int currentIndex = 0;

        void start() {
            if (isPaused) {
                mPlayer.start();
            } else if (!mPlayer.isPlaying()) {
                startNew();
            }
            isPaused = false;
        }

        void pause() {
            if (mPlayer.isPlaying()) {
                mPlayer.pause();
                isPaused = true;
            }
        }

        void stop() {
            mPlayer.stop();
            isPaused = false;
        }

        void playNext() {
            currentIndex++;
            startNew();
            isPaused = false;
        }

        void playPrev() {
            currentIndex--;
            startNew();
            isPaused = false;
        }

        void startNew() {
            if (playlist.size() <= 0) return;
            if (currentIndex < 0) {
                currentIndex = playlist.size() - 1;
            } else if (currentIndex >= playlist.size()) {
                currentIndex = 0;
            }
            String str = playlist.get(currentIndex);
            str = currentIndex + ", " + str.substring(str.lastIndexOf("/") + 1);
            tvTitle.setText(str);
            mPlayer.reset();
            try {
                mPlayer.setDataSource(playlist.get(currentIndex));
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                    AudioAttributes aa = new AudioAttributes.Builder()
                            .setUsage(AudioAttributes.USAGE_MEDIA)
                            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                            .build();
                    mPlayer.setAudioAttributes(aa);
                } else {
                    mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                }
                mPlayer.prepare();
                mPlayer.start();
            } catch (Exception e) {
                e.printStackTrace();
                showMsg(e.getMessage());
            }
        }

        void playOrPause() {
            if (isPaused) {
                start();
            } else {
                pause();
            }
        }
    }

    private void showPlayList() {
        ScrollView sv = new ScrollView(mActivity);
        LinearLayout ly = new LinearLayout(mActivity);
        ly.setOrientation(LinearLayout.VERTICAL);
        sv.addView(ly);
        final AlertDialog ad = new AlertDialog.Builder(mActivity)
                .setView(sv)
                .setPositiveButton(android.R.string.ok, null)
                .create();
        for (int i = 0; i < playlist.size(); i++) {
            MarqueeTextView mtv = new MarqueeTextView(mActivity);
            mtv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 24);
            String str = playlist.get(i);
            str = i + ", " + str.substring(str.lastIndexOf("/") + 1);
            mtv.setText(str);
            if (i == musicCtrl.currentIndex) {
                mtv.setBackgroundColor(0xff8888ff);
            }
            final int finalI = i;
            mtv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    musicCtrl.currentIndex = finalI;
                    musicCtrl.startNew();
                    ad.dismiss();
                }
            });
            ly.addView(mtv);
        }
        ad.show();
    }
}
